using SqlSugar;
using IM.Easy.Core.Services;
using IM.Easy.Core.Utils;
using IM.Easy.Infrastructure.Query;
using IM.Easy.Entity.System;
using IM.Easy.SystemServices.Dtos;
using IM.Easy.SystemServices.IServices;
using IM.Easy.Core.Extensions;
using System.Data;
using static Dm.net.buffer.ByteArrayBuffer;
using IM.Easy.SystemServices.Dtos.User;
using IM.Easy.SystemServices.Dtos.Role;

namespace IM.Easy.SystemServices.Services
{
    public class RoleService(ISqlSugarClient db) : AppServices<SysRole>(db), IRoleService
    {
        public SysRole Create(SysRole entity)
        {
            if (!RoleValidate(entity, out string msg)) ExceptionUtils.ThrowBusinessException(msg);
            return Db.Insertable(entity).ExecuteReturnEntity();
        }

        public SysRole GetById(long id)
        {
            // TODO: 添加获取逻辑
            return Db.Queryable<SysRole>().InSingle(id);
        }

        /// <summary>
        /// 通过角色编码获取角色信息
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public SysRole GetByCode(string code)
        {
            return Db.Queryable<SysRole>().Single(s => s.Code == code);
        }

        public PageResponse<SysRole> GetPageList(SysRoleQueryDto query)
        {
            var list = Db.Queryable<SysRole>();
            var exp = Expressionable.Create<SysRole>();
            exp = exp.AndIF(!string.IsNullOrEmpty(query.Name), s => s.Name.Contains(query.Name))
                    .AndIF(query.IsActive.HasValue, s => SqlFunc.Equals(s.IsActive, query.IsActive))
;
            var page = list
                 .Where(exp.ToExpression())
                 .ToPageList<SysRole, SysRole>(query);
            return page;
        }

        public bool UpdateRole(SysRole entity)
        {
            if (!RoleValidate(entity, out string msg)) ExceptionUtils.ThrowBusinessException(msg);
            return Db.Updateable(entity).ExecuteCommandHasChange();
        }

        /// <summary>
        /// 权限字符校验
        /// </summary>
        /// <param name="roleId">角色ID（更新时需要排除自身）</param>
        /// <param name="code">权限字符</param>
        /// <param name="msg">返回校验结果信息</param>
        /// <returns>true：校验通过；false：校验失败</returns>
        private bool CodeValidate(long roleId, string code, out string msg)
        {
            msg = string.Empty;

            // 1. 空值或空白字符串检查
            if (string.IsNullOrWhiteSpace(code))
            {
                msg = "权限字符不能为空";
                return false;
            }

            // 2. （可选）格式检查，例如只允许字母、数字、下划线和短横线
            // using System.Text.RegularExpressions;
            // if (!Regex.IsMatch(code, @"^[a-zA-Z0-9-_]+$"))
            // {
            //     msg = "权限字符只能包含字母、数字、下划线和短横线";
            //     return false;
            // }

            // 3. 长度检查（根据业务需求进行调整）
            int maxLength = 10;
            if (code.Length > maxLength)
            {
                msg = $"权限字符长度不能超过 {maxLength} 个字符";
                return false;
            }

            // 4. 使用 SqlSugar 进行重复校验（排除自身角色ID）
            bool exist = Context.Queryable<SysRole>()
                                .Any(r => r.Code == code && r.Id != roleId);
            if (exist)
            {
                msg = $"权限字符 [{code}] 已存在，请更换后重试。";
                return false;
            }

            msg = "校验成功";
            return true;
        }

        /// <summary>
        /// 校验名称是否重复
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        private bool NameDuplicate(long roleId, string name, out string msg)
        {
            bool exist = Context.Queryable<SysRole>()
                                .Any(r => r.Name == name && r.Id != roleId);
            msg = exist ? $"角色名称 [{name}] 已存在，请更换后重试。" : "校验成功";
            return !exist;
        }

        /// <summary>
        /// 角色合法性校验
        /// </summary>
        /// <param name="role">角色实体</param>
        /// <param name="msg">返回校验结果信息</param>
        /// <returns>true：校验通过；false：校验失败</returns>
        private bool RoleValidate(SysRole role, out string msg)
        {
            if (!CodeValidate(role.Id, role.Code, out msg)) return false;
            if (!NameDuplicate(role.Id, role.Name, out msg)) return false;
            msg = "校验成功";
            return true;
        }



        public bool DeleteRole(params long[] Id)
        {

            var flag = Context.DeleteNav<SysRole>(s => Id.Contains(s.Id))
                  .Include(s => s.Users, new DeleteNavOptions { ManyToManyIsDeleteA = true })
                  .Include(s => s.Menus, new DeleteNavOptions { ManyToManyIsDeleteA = true })
                  .ExecuteCommand();
            return flag;
        }

        /// <summary>
        /// 根据角色获取用户
        /// </summary>
        public PageResponse<UserDto> GetUsers(UserRoleQueryDto query)
        {
            var exp = Expressionable.Create<SysUser, SysUserRole>();
            exp = exp.AndIF(!string.IsNullOrEmpty(query.UserName), (u, ur) => u.UserName.Contains(query.UserName))
                    .AndIF(!string.IsNullOrEmpty(query.Mobile), (u, ur) => u.Mobile.Contains(query.Mobile))
                    .And((u, ur) => ur.RoleId == query.RoleId);
            var page = Db.Queryable<SysUser>()
                        .InnerJoin<SysUserRole>((u, ur) => u.Id == ur.UserId)
                        .Where(exp.ToExpression())
                        .Select((u, ur) => u)
                        .Select<UserDto>()
                        .ToPageList(query);
            return page;
        }

        /// <summary>
        /// 获取不在某个角色中的用户
        /// </summary>
        public PageResponse<UserDto> GetUsersNotIn(UserRoleQueryDto query)
        {
            var exp = Expressionable.Create<SysUser, SysUserRole>();
            exp = exp.AndIF(!string.IsNullOrEmpty(query.UserName), (u, ur) => u.UserName.Contains(query.UserName))
                    .AndIF(!string.IsNullOrEmpty(query.Mobile), (u, ur) => u.Mobile.Contains(query.Mobile))
                    .And((u, ur) => SqlFunc.IsNullOrEmpty(ur.UserId));  // 筛选出未分配该角色的用户
            var page = Db.Queryable<SysUser>()
                     .LeftJoin<SysUserRole>((u, ur) => u.Id == ur.UserId && ur.RoleId == query.RoleId)
                     .Where(exp.ToExpression())
                     .Select(u => u)
                     .Select<UserDto>()
                     .ToPageList(query);
            return page;
        }

        /// <summary>
        /// 为用户设置角色
        /// </summary>
        /// <param name="uid"></param>
        public void SetRole(long roleId, params long[] uid)
        {
            var userRoles = uid.Select(item => new SysUserRole { RoleId = roleId, UserId = item }).ToList();
            Db.Storageable(userRoles).ExecuteCommand();
        }

        /// <summary>
        /// 取消用户的角色分配
        /// </summary>
        /// <param name="roleId">角色ID</param>
        /// <param name="uid">用户ID列表</param>
        public void RemoveRole(long roleId, params long[] uid)
        {
            Db.Deleteable<SysUserRole>()
                .Where(ur => ur.RoleId == roleId && uid.Contains(ur.UserId))
                .ExecuteCommand();
        }

    }
}
